package regist;

import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Date;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.sql.SqlExecutor;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import regist.aliutil.Config;

public class MyServer {
	
			
	static EventLoopGroup bossGroup = new NioEventLoopGroup();
	static EventLoopGroup workerGroup = new NioEventLoopGroup();
	
	public static void nettyServer() throws InterruptedException {
		try {
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
			.childHandler(new MyServerInitializer());
			ChannelFuture channelFuture = serverBootstrap.bind(Integer.parseInt(PropertyConfig.getStr("port"))).sync();
			channelFuture.channel().closeFuture().sync();
		}finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}

class MyServerInitializer extends ChannelInitializer<SocketChannel>{

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		// TODO Auto-generated method stub
	ChannelPipeline pipeline = ch.pipeline();
	pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2,0,2));
	//pipeline.addLast(new LengthFieldPrepender(2));
	//pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
	//pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
	pipeline.addLast(new  MyServerHandler());
	}
}

class MyServerHandler extends ChannelInboundHandlerAdapter{
	
	private static Logger logger = LoggerFactory.getLogger(MyServerHandler.class);
	String key ="tuorenzhinenghua";
	AliDeviceRegist regist = new AliDeviceRegist();
	DataSource ds = PropertyConfig.getDs();
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		// TODO Auto-generated method stub
		//打印出客户端地址
		ByteBuf result = (ByteBuf)msg;
		byte[] resultByte = new byte[result.readableBytes()];
		result.readBytes(resultByte);
		result.release();
		String msgStr = AES.decrypt(resultByte,key);
        System.out.println("aes decrypt:"+msgStr);
        logger.info("aes decrypt:"+msgStr);
        String jsonString = "{\"code\":\"1\"}";
        String ip = ctx.channel().remoteAddress().toString();
        logger.info("regist ip :"+ip);
        
        try {
        	jsonString = handleRegist(msgStr);
        }catch (Exception e) {
			// TODO: handle exception
        	logger.error("regist error:"+e);
		}
        
        byte[] resultRegist = AES.encrypt(jsonString,key);
        ByteBuf encoded = ctx.alloc().buffer(2 * resultRegist.length);  
       
        encoded.writeBytes(resultRegist);
        ctx.channel().writeAndFlush(encoded);
        ctx.flush();
	}
	
	private String handleRegist(String msgStr) throws Exception{
		JSONObject json = new JSONObject();
        json.put("code", 1);
        
        if(StrUtil.isBlank(msgStr)) {
        	return json.toString();
        }
   
        String[] prodata = msgStr.split("&");
        boolean deviceExist = false;
        if(prodata.length <= 2){
        	return json.toString();
        }
        String deviceName = prodata[0];
        String simIccid = prodata[1];
        String version = "";
        if(prodata.length > 2) {
        	version = prodata[2];
        }
        
        Connection conn = ds.getConnection();
        ResultSet resultSet =  SqlExecutor.callQuery(conn, "select mqtt_conn_info,is_delete from bus_device where device_id = ? limit 1", deviceName);
        if(resultSet.next()){
        	SqlExecutor.execute(conn, "update bus_device set sim_iccid = ?,version = ?,create_time = ? where  device_id = ? ", simIccid,version,new Date(),deviceName);
        	String jsonString = resultSet.getString(1);
        	int isDelete = resultSet.getInt(2);
        	if(isDelete == 0){
        		deviceExist = true;
        	}
        	if(deviceExist && StrUtil.isNotBlank(jsonString)){
        		if(!conn.getAutoCommit()){              	
              		conn.commit();
              	}
        		conn.close();
        		return jsonString;
        	}
        }else{
        	SqlExecutor.execute(conn, "insert into bus_device(id,device_id,tenant_id,sim_iccid,version,create_time,create_by)values(?,?,?,?,?,?,?) "
        			,IdUtil.getSnowflakeNextIdStr(),deviceName,"1",simIccid,version,new Date(),"1" );
        	 if(!conn.getAutoCommit()){
         		conn.commit();
         	 }
        }
        
        
        JSONObject registData = AliDeviceHttp.deviceRegist(deviceName);
        if(registData.isEmpty()) {
        	registData = AliDeviceHttp.deviceQuery(deviceName); 
        }
        if(!registData.isEmpty()) {
        	json.put("code", 0);
        	json.put("type", 0x15);
        	json.put("address",Config.COAP_ADDRESS);
        	json.put("port",Config.COAP_PORT);
        	json.put("deviceName", deviceName);
        	json.put("deviceSecret", registData.getString("DeviceSecret"));
        	json.put("productKey", registData.getString("ProductKey"));
			SqlExecutor.execute(conn, "update bus_device set mqtt_conn_info = ? where  device_id = ? ", json.toString(),deviceName);
        }
        
        
        if(!conn.getAutoCommit())
    	{
    		conn.commit();
    	}
        conn.close();
        
        return json.toString();
	}
}